@@ -25,6 +25,9 @@
#define MB2_HT(name) (MULTIBOOT2_HEADER_TAG_##name)
#define MB2_TT(name) (MULTIBOOT2_TAG_TYPE_##name)
+#define BOOT_TYPE_BIOS 1
+#define BOOT_TYPE_PVH 2
+
.macro mb2ht_args arg:req, args:vararg
.long \arg
.ifnb \args
@@ -409,17 +412,31 @@ cs32_switch:
ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .long sym_offs(__pvh_start))
__pvh_start:
- cld
+ mov $BOOT_TYPE_PVH, %dl
+ jmp .Lcommon_bios_pvh
+#endif /* CONFIG_PVH_GUEST */
+
+__start:
+ mov $BOOT_TYPE_BIOS, %dl
+
+.Lcommon_bios_pvh:
cli
+ cld
/*
- * We need one call (i.e. push) to determine the load address. See
- * __start for a discussion on how to do this safely using the PVH
- * info structure.
+ * Multiboot (both 1 and 2) and PVH specify the stack pointer as
+ * undefined. This is unhelpful for relocatable images, where one
+ * call (i.e. push) is required to calculate the image's load address.
+ *
+ * Durig BIOS boot, there is one area of memory we know about with
+ * reasonable confidence that it isn't overlapped by Xen, and that's
+ * the Multiboot info structure in %ebx. Use it as a temporary stack.
+ *
+ * During PVH boot use info structure in %ebx.
*/
/* Preserve the field we're about to clobber. */
- mov (%ebx), %edx
+ mov (%ebx), %ecx
lea 4(%ebx), %esp
/* Calculate the load base address. */
@@ -428,19 +445,12 @@ __pvh_start:
sub $sym_offs(1b), %esi
/* Restore the clobbered field. */
- mov %edx, (%ebx)
+ mov %ecx, (%ebx)
/* Set up stack. */
lea STACK_SIZE - CPUINFO_sizeof + sym_esi(cpu0_stack), %esp
- call .Linitialise_bss
-
- mov %ebx, sym_esi(pvh_start_info_pa)
-
- /* Force xen console. Will revert to user choice in init code. */
- movb $-1, sym_esi(opt_console_xen)
-
- /* Prepare gdt and segments */
+ /* Initialize GDTR and basic data segments. */
add %esi, sym_esi(gdt_boot_base)
lgdt sym_esi(gdt_boot_descr)
@@ -449,67 +459,44 @@ __pvh_start:
mov %ecx, %es
mov %ecx, %ss
- /* Skip bootloader setup and bios setup, go straight to trampoline */
- movb $1, sym_esi(pvh_boot)
- movb $1, sym_esi(skip_realmode)
-
- /* Set trampoline_phys to use mfn 1 to avoid having a mapping at VA 0 */
- movw $0x1000, sym_esi(trampoline_phys)
- mov (%ebx), %eax /* mov $XEN_HVM_START_MAGIC_VALUE, %eax */
- jmp trampoline_setup
-
-#endif /* CONFIG_PVH_GUEST */
+ /* Load null selector to unused segment registers. */
+ xor %ecx, %ecx
+ mov %ecx, %fs
+ mov %ecx, %gs
-.Linitialise_bss:
/*
* Initialise the BSS.
*
* !!! WARNING - also zeroes the current stack !!!
*/
- pop %ebp
- mov %eax, %edx
-
+ mov %eax, %ebp
lea sym_esi(__bss_start), %edi
lea sym_esi(__bss_end), %ecx
sub %edi, %ecx
xor %eax, %eax
shr $2, %ecx
rep stosl
+ mov %ebp, %eax
- mov %edx, %eax
- jmp *%ebp
-
-__start:
- cld
- cli
-
- /*
- * Multiboot (both 1 and 2) specify the stack pointer as undefined
- * when entering in BIOS circumstances. This is unhelpful for
- * relocatable images, where one call (i.e. push) is required to
- * calculate the image's load address.
- *
- * This early in boot, there is one area of memory we know about with
- * reasonable confidence that it isn't overlapped by Xen, and that's
- * the Multiboot info structure in %ebx. Use it as a temporary stack.
- */
-
- /* Preserve the field we're about to clobber. */
- mov (%ebx), %edx
- lea 4(%ebx), %esp
+#ifdef CONFIG_PVH_GUEST
+ cmp $BOOT_TYPE_PVH, %dl
+ jne 1f
- /* Calculate the load base address. */
- call 1f
-1: pop %esi
- sub $sym_offs(1b), %esi
+ mov %ebx, sym_esi(pvh_start_info_pa)
- /* Restore the clobbered field. */
- mov %edx, (%ebx)
+ /* Force xen console. Will revert to user choice in init code. */
+ movb $-1, sym_esi(opt_console_xen)
- /* Set up stack. */
- lea STACK_SIZE - CPUINFO_sizeof + sym_esi(cpu0_stack), %esp
+ /* Skip bootloader setup and bios setup, go straight to trampoline */
+ movb $1, sym_esi(pvh_boot)
+ movb $1, sym_esi(skip_realmode)
- call .Linitialise_bss
+ /* Set trampoline_phys to use mfn 1 to avoid having a mapping at VA 0 */
+ movl $PAGE_SIZE, sym_esi(trampoline_phys)
+ mov (%ebx), %eax /* mov $XEN_HVM_START_MAGIC_VALUE, %eax */
+ jmp trampoline_setup
+1:
+#endif /* CONFIG_PVH_GUEST */
/* Bootloaders may set multiboot{1,2}.mem_lower to a nonzero value. */
xor %edx,%edx
@@ -568,22 +555,7 @@ __start:
trampoline_bios_setup:
/*
* Called on legacy BIOS platforms only.
- *
- * Initialize GDTR and basic data segments.
*/
- add %esi,sym_esi(gdt_boot_base)
- lgdt sym_esi(gdt_boot_descr)
-
- mov $BOOT_DS,%ecx
- mov %ecx,%ds
- mov %ecx,%es
- mov %ecx,%ss
- /* %esp is initialized later. */
-
- /* Load null descriptor to unused segment registers. */
- xor %ecx,%ecx
- mov %ecx,%fs
- mov %ecx,%gs
/* Set up trampoline segment 64k below EBDA */
movzwl 0x40e,%ecx /* EBDA segment */
The 2 code paths were sharing quite some common code, reuse it instead of having duplications. Use %dl register to store boot type before running common code. Using a 8 bit register reduces code size. Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com> --- Changes since v1: - use %dl instead of %ebp to reduce code size; - fold cli instruction; - update some comments. --- xen/arch/x86/boot/head.S | 118 +++++++++++++++------------------------ 1 file changed, 45 insertions(+), 73 deletions(-)