File 25479-x86-boot-trampoline-remove.patch of Package xen.openSUSE_12.1_Update
# HG changeset patch
# User Jan Beulich <jbeulich@novell.com>
# Date 1313744093 -3600
# Node ID dd90b59cb11c60c48e174c899190e2967341fe32
# Parent 29aeed4979a78f26519f5fde8a405f8438297ab9
x86: trampoline cleanup
To make future changes less error prone, and to slightly simplify a
possible future conversion to a relocatable trampoline even for the
multiboot path (pretty desirable given that we had to change the
trampoline base a number of times to escape collisions with firmware
placed data),
- remove final uses of bootsym_phys() from trampoline.S, allowing the
symbol to be undefined before including this file (to make sure no
new references get added)
- replace two easy to deal with uses of bootsym_phys() in head.S
- remove an easy to replace reference to BOOT_TRAMPOLINE
Signed-off-by: Jan Beulich <jbeulich@novell.com>
# HG changeset patch
# User Jan Beulich <jbeulich@suse.com>
# Date 1339424128 -3600
# Node ID 61dfb3da56b0a3ac86f81f4a8770e11e1dbc2aa9
# Parent 6d1a30dc47e8dfcb826ff14c833d694fd4e6afb2
x86: get rid of BOOT_TRAMPOLINE
We recently saw a machine that has the EBDA extending as low as
0x7c000, so that Xen fails to boot after relocating the trampoline.
To fix this, I removed BOOT_TRAMPOLINE and bootsym_phys completely.
Here are the parts:
1) the trampoline segment is set to 64k below the EBDA. head.S grows
the ability to relocate the trampoline segment
2) reloc.c is made position-independent. It allocates data below the
trampoline, whose address is passed in _eax.
3) cmdline.S is called before relocating, so all bootsym_phys there
become sym_phys.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
jb: - fall back to low memory size (instead of segment 0x7c00) if EBDA
value is out of range
- also add upper limit check on EBDA value
- fix and simplify inline assembly operands in reloc_mbi_struct()
- use lret instead of retf
- renamed early_stack to wakeup_stack, defined and used now only
in wakeup.S
- aligned reloc.bin's end of .text to 16 bytes, so that checking
__bss_start == end works reliably
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Committed-by: Keir Fraser <keir@xen.org>
Index: xen-4.1.4-testing/xen/arch/x86/boot/Makefile
===================================================================
--- xen-4.1.4-testing.orig/xen/arch/x86/boot/Makefile
+++ xen-4.1.4-testing/xen/arch/x86/boot/Makefile
@@ -2,8 +2,7 @@ obj-y += head.o
head.o: reloc.S
-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 $@
+ $(MAKE) -f build32.mk $@
reloc.S: head.S
Index: xen-4.1.4-testing/xen/arch/x86/boot/build32.mk
===================================================================
--- xen-4.1.4-testing.orig/xen/arch/x86/boot/build32.mk
+++ xen-4.1.4-testing/xen/arch/x86/boot/build32.mk
@@ -15,9 +15,10 @@ CFLAGS += -Werror -fno-builtin -msoft-fl
$(OBJCOPY) -O binary $< $@
%.lnk: %.o
- $(LD) $(LDFLAGS_DIRECT) -N -Ttext $(RELOC) -o $@ $<
+ $(LD) $(LDFLAGS_DIRECT) -N -Ttext 0 -o $@ $<
%.o: %.c
- $(CC) $(CFLAGS) -c $< -o $@
+ $(CC) $(CFLAGS) -c -fpic $< -o $@
reloc.o: $(BASEDIR)/include/asm-x86/config.h
+.PRECIOUS: %.bin %.lnk
Index: xen-4.1.4-testing/xen/arch/x86/boot/cmdline.S
===================================================================
--- xen-4.1.4-testing.orig/xen/arch/x86/boot/cmdline.S
+++ xen-4.1.4-testing/xen/arch/x86/boot/cmdline.S
@@ -165,14 +165,14 @@ cmdline_parse_early:
call .Lfind_option
test %eax,%eax
setnz %al
- or %al,bootsym_phys(skip_realmode)
+ or %al,sym_phys(skip_realmode)
/* Check for 'tboot=' command-line option. */
movl $sym_phys(.Ltboot_opt),4(%esp)
call .Lfind_option
test %eax,%eax
setnz %al
- or %al,bootsym_phys(skip_realmode) /* tboot= implies no-real-mode */
+ or %al,sym_phys(skip_realmode) /* tboot= implies no-real-mode */
.Lparse_edd:
/* Check for 'edd=' command-line option. */
@@ -183,13 +183,13 @@ cmdline_parse_early:
cmpb $'=',3(%eax)
jne .Lparse_edid
add $4,%eax
- movb $2,bootsym_phys(opt_edd) /* opt_edd=2: edd=off */
+ movb $2,sym_phys(opt_edd) /* opt_edd=2: edd=off */
cmpw $0x666f,(%eax) /* 0x666f == "of" */
je .Lparse_edid
- decb bootsym_phys(opt_edd) /* opt_edd=1: edd=skipmbr */
+ decb sym_phys(opt_edd) /* opt_edd=1: edd=skipmbr */
cmpw $0x6b73,(%eax) /* 0x6b73 == "sk" */
je .Lparse_edid
- decb bootsym_phys(opt_edd) /* opt_edd=0: edd=on (default) */
+ decb sym_phys(opt_edd) /* opt_edd=0: edd=on (default) */
.Lparse_edid:
/* Check for 'edid=' command-line option. */
@@ -205,17 +205,17 @@ cmdline_parse_early:
pushl $sym_phys(.Ledid_force)
call .Lstr_prefix
add $8,%esp
- movb $2,bootsym_phys(opt_edid) /* opt_edid=2: edid=force */
+ movb $2,sym_phys(opt_edid) /* opt_edid=2: edid=force */
test %eax,%eax
jz .Lparse_vga
push %ebx
pushl $sym_phys(.Ledid_no)
call .Lstr_prefix
add $8,%esp
- decb bootsym_phys(opt_edid) /* opt_edid=1: edid=no */
+ decb sym_phys(opt_edid) /* opt_edid=1: edid=no */
test %eax,%eax
jz .Lparse_vga
- decb bootsym_phys(opt_edid) /* opt_edid=0: default */
+ decb sym_phys(opt_edid) /* opt_edid=0: default */
.Lparse_vga:
/* Check for 'vga=' command-line option. */
@@ -229,7 +229,7 @@ cmdline_parse_early:
add $4,%eax
/* Found the 'vga=' option. Default option is to display vga menu. */
- movw $ASK_VGA,bootsym_phys(boot_vid_mode)
+ movw $ASK_VGA,sym_phys(boot_vid_mode)
/* Check for 'vga=text-80x<rows>. */
mov %eax,%ebx
@@ -253,7 +253,7 @@ cmdline_parse_early:
cmp %ax,%bx
lodsw
jne 1b
- mov %ax,bootsym_phys(boot_vid_mode)
+ mov %ax,sym_phys(boot_vid_mode)
jmp .Lcmdline_exit
.Lparse_vga_gfx:
@@ -272,7 +272,7 @@ cmdline_parse_early:
push %ebx
call .Latoi
pop %esi
- mov %ax,bootsym_phys(vesa_size)+0
+ mov %ax,sym_phys(vesa_size)+0
/* skip 'x' */
lodsb
cmpb $'x',%al
@@ -281,7 +281,7 @@ cmdline_parse_early:
push %esi
call .Latoi
pop %esi
- mov %ax,bootsym_phys(vesa_size)+2
+ mov %ax,sym_phys(vesa_size)+2
/* skip 'x' */
lodsb
cmpb $'x',%al
@@ -290,9 +290,9 @@ cmdline_parse_early:
push %esi
call .Latoi
pop %esi
- mov %ax,bootsym_phys(vesa_size)+4
+ mov %ax,sym_phys(vesa_size)+4
/* commit to vesa mode */
- movw $VIDEO_VESA_BY_SIZE,bootsym_phys(boot_vid_mode)
+ movw $VIDEO_VESA_BY_SIZE,sym_phys(boot_vid_mode)
jmp .Lcmdline_exit
.Lparse_vga_mode:
@@ -309,7 +309,7 @@ cmdline_parse_early:
push %ebx
call .Latoi
add $4,%esp
- mov %ax,bootsym_phys(boot_vid_mode)
+ mov %ax,sym_phys(boot_vid_mode)
jmp .Lcmdline_exit
.Lparse_vga_current:
@@ -322,7 +322,7 @@ cmdline_parse_early:
jnz .Lcmdline_exit
/* We have 'vga=current'. */
- movw $VIDEO_CURRENT_MODE,bootsym_phys(boot_vid_mode)
+ movw $VIDEO_CURRENT_MODE,sym_phys(boot_vid_mode)
.Lcmdline_exit:
popa
Index: xen-4.1.4-testing/xen/arch/x86/boot/head.S
===================================================================
--- xen-4.1.4-testing.orig/xen/arch/x86/boot/head.S
+++ xen-4.1.4-testing/xen/arch/x86/boot/head.S
@@ -9,9 +9,7 @@
.text
.code32
-#define BOOT_TRAMPOLINE 0x7c000
#define sym_phys(sym) ((sym) - __XEN_VIRT_START)
-#define bootsym_phys(sym) ((sym) - trampoline_start + BOOT_TRAMPOLINE)
#define BOOT_CS32 0x0008
#define BOOT_CS64 0x0010
@@ -79,6 +77,23 @@ __start:
cmp $0x2BADB002,%eax
jne not_multiboot
+ /* Set up trampoline segment 64k below EBDA */
+ movzwl 0x40e,%eax /* EBDA segment */
+ cmp $0xa000,%eax /* sanity check (high) */
+ jae 0f
+ cmp $0x4000,%eax /* sanity check (low) */
+ jae 1f
+0:
+ movzwl 0x413,%eax /* use base memory size on failure */
+ shl $10-4,%eax
+1:
+ sub $0x1000,%eax
+
+ /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */
+ xor %al, %al
+ shl $4, %eax
+ mov %eax,sym_phys(trampoline_phys)
+
/* Save the Multiboot info struct (after relocation) for later use. */
mov $sym_phys(cpu0_stack)+1024,%esp
push %ebx
@@ -190,7 +205,7 @@ __start:
#endif
/* Apply relocations to bootstrap trampoline. */
- mov $BOOT_TRAMPOLINE,%edx
+ mov sym_phys(trampoline_phys),%edx
mov $sym_phys(__trampoline_rel_start),%edi
mov %edx,sym_phys(trampoline_phys)
1:
@@ -200,17 +215,32 @@ __start:
cmp $sym_phys(__trampoline_rel_stop),%edi
jb 1b
+ /* Patch in the trampoline segment. */
+ shr $4,%edx
+ mov $sym_phys(__trampoline_seg_start),%edi
+1:
+ mov (%edi),%eax
+ mov %dx,(%edi,%eax)
+ add $4,%edi
+ cmp $sym_phys(__trampoline_seg_stop),%edi
+ jb 1b
+
+ call cmdline_parse_early
+
+ /* Switch to low-memory stack. */
+ mov sym_phys(trampoline_phys),%edi
+ lea 0x10000(%edi),%esp
+ lea trampoline_boot_cpu_entry-trampoline_start(%edi),%eax
+ pushl $BOOT_CS32
+ push %eax
+
/* Copy bootstrap trampoline to low memory, below 1MB. */
mov $sym_phys(trampoline_start),%esi
- mov $bootsym_phys(trampoline_start),%edi
mov $trampoline_end - trampoline_start,%ecx
rep movsb
- mov $bootsym_phys(early_stack),%esp
- call cmdline_parse_early
-
/* Jump into the relocated trampoline. */
- jmp $BOOT_CS32,$bootsym_phys(trampoline_boot_cpu_entry)
+ lret
#include "cmdline.S"
Index: xen-4.1.4-testing/xen/arch/x86/boot/reloc.c
===================================================================
--- xen-4.1.4-testing.orig/xen/arch/x86/boot/reloc.c
+++ xen-4.1.4-testing/xen/arch/x86/boot/reloc.c
@@ -10,42 +10,49 @@
* Keir Fraser <keir@xen.org>
*/
+/* entered with %eax = BOOT_TRAMPOLINE */
asm (
" .text \n"
" .globl _start \n"
"_start: \n"
- " mov $_start,%edi \n"
" call 1f \n"
- "1: pop %esi \n"
- " sub $1b-_start,%esi \n"
- " mov $__bss_start-_start,%ecx \n"
- " rep movsb \n"
- " xor %eax,%eax \n"
- " mov $_end,%ecx \n"
- " sub %edi,%ecx \n"
- " rep stosb \n"
- " mov $reloc,%eax \n"
- " jmp *%eax \n"
+ "1: pop %ebx \n"
+ " mov %eax,alloc-1b(%ebx) \n"
+ " mov $_end,%ecx \n" /* check that BSS is empty! */
+ " sub $__bss_start,%ecx \n"
+ " jz reloc \n"
+ "1: jmp 1b \n"
+ );
+
+/* This is our data. Because the code must be relocatable, no BSS is
+ * allowed. All data is accessed PC-relative with inline assembly.
+ */
+asm (
+ "alloc: \n"
+ " .long 0 \n"
+ " .subsection 1 \n"
+ " .p2align 4, 0xcc \n"
+ " .subsection 0 \n"
);
typedef unsigned int u32;
#include "../../../include/xen/multiboot.h"
-extern char _start[];
-
-static void *memcpy(void *dest, const void *src, unsigned int n)
-{
- char *s = (char *)src, *d = dest;
- while ( n-- )
- *d++ = *s++;
- return dest;
-}
-
static void *reloc_mbi_struct(void *old, unsigned int bytes)
{
- static void *alloc = &_start;
- alloc = (void *)(((unsigned long)alloc - bytes) & ~15ul);
- return memcpy(alloc, old, bytes);
+ void *new;
+ asm(
+ " call 1f \n"
+ "1: pop %%edx \n"
+ " mov alloc-1b(%%edx),%0 \n"
+ " sub %1,%0 \n"
+ " and $~15,%0 \n"
+ " mov %0,alloc-1b(%%edx) \n"
+ " mov %0,%%edi \n"
+ " rep movsb \n"
+ : "=&r" (new), "+c" (bytes), "+S" (old)
+ : : "edx", "edi");
+ return new;
}
static char *reloc_mbi_string(char *old)
Index: xen-4.1.4-testing/xen/arch/x86/boot/trampoline.S
===================================================================
--- xen-4.1.4-testing.orig/xen/arch/x86/boot/trampoline.S
+++ xen-4.1.4-testing/xen/arch/x86/boot/trampoline.S
@@ -11,6 +11,13 @@
.long 111b - (off) - .; \
.popsection
+#define bootsym_segrel(sym, off) \
+ $0,$bootsym(sym); \
+111:; \
+ .pushsection .trampoline_seg, "a"; \
+ .long 111b - (off) - .; \
+ .popsection
+
.globl trampoline_realmode_entry
trampoline_realmode_entry:
mov %cs,%ax
@@ -132,7 +139,7 @@ high_start:
.code32
trampoline_boot_cpu_entry:
- cmpb $0,bootsym_phys(skip_realmode)
+ cmpb $0,bootsym_rel(skip_realmode,5)
jnz .Lskip_realmode
/* Load pseudo-real-mode segments. */
@@ -151,14 +158,14 @@ trampoline_boot_cpu_entry:
1: mov %eax,%cr0 # CR0.PE = 0 (leave protected mode)
/* Load proper real-mode values into %cs, %ds, %es and %ss. */
- ljmp $(BOOT_TRAMPOLINE>>4),$bootsym(1f)
-1: mov $(BOOT_TRAMPOLINE>>4),%ax
+ ljmp bootsym_segrel(1f,2)
+1: mov %cs,%ax
mov %ax,%ds
mov %ax,%es
mov %ax,%ss
/* Initialise stack pointer and IDT, and enable irqs. */
- mov $bootsym(early_stack),%sp
+ xor %sp,%sp
lidt bootsym(rm_idt)
sti
@@ -195,7 +202,7 @@ trampoline_boot_cpu_entry:
lmsw %ax # CR0.PE = 1 (enter protected mode)
/* Load proper protected-mode values into all segment registers. */
- ljmpl $BOOT_CS32,$bootsym_phys(1f)
+ ljmpl $BOOT_CS32,$bootsym_rel(1f,6)
.code32
1: mov $BOOT_DS,%eax
mov %eax,%ds
@@ -220,7 +227,3 @@ rm_idt: .word 256*4-1, 0, 0
#include "edd.S"
#include "video.S"
#include "wakeup.S"
-
- .align 16
- .fill PAGE_SIZE,1,0
-early_stack:
Index: xen-4.1.4-testing/xen/arch/x86/boot/wakeup.S
===================================================================
--- xen-4.1.4-testing.orig/xen/arch/x86/boot/wakeup.S
+++ xen-4.1.4-testing/xen/arch/x86/boot/wakeup.S
@@ -11,7 +11,7 @@ ENTRY(wakeup_start)
movw %cs, %ax
movw %ax, %ds
movw %ax, %ss # A stack required for BIOS call
- movw $wakesym(early_stack), %sp
+ movw $wakesym(wakeup_stack), %sp
pushl $0 # Kill dangerous flag early
popfl
@@ -101,7 +101,7 @@ real_magic: .long 0x12345678
.globl video_mode, video_flags
video_mode: .long 0
video_flags: .long 0
-trampoline_seg: .word BOOT_TRAMPOLINE >> 4
+trampoline_seg: .word 0
.pushsection .trampoline_seg, "a"
.long trampoline_seg - .
.popsection
@@ -116,7 +116,7 @@ wakeup_32:
mov $BOOT_DS, %eax
mov %eax, %ds
mov %eax, %ss
- mov $bootsym_rel(early_stack, 4, %esp)
+ mov $bootsym_rel(wakeup_stack, 4, %esp)
# check saved magic again
mov $sym_phys(saved_magic), %eax
@@ -188,3 +188,7 @@ ret_point:
bogus_saved_magic:
movw $0x0e00 + 'S', 0xb8014
jmp bogus_saved_magic
+
+ .align 16
+ .fill PAGE_SIZE,1,0
+wakeup_stack: