From 418e5c1b38e3c037539a03c27d62af39b24a54d0 Mon Sep 17 00:00:00 2001 From: "Charles E. Youse" Date: Sat, 28 Sep 2019 16:16:19 -0400 Subject: [PATCH] arch/x86: factor out common assembly startup code The 32-bit and 64-bit assembly startup sequences share quite a bunch of common code, so it's factored out into one file to avoid repeating ourselves (and potentially falling out of sync). Signed-off-by: Charles E. Youse --- arch/x86/core/common.S | 67 ++++++++++++++++++++++++++++++++++ arch/x86/core/ia32/crt0.S | 66 +-------------------------------- arch/x86/core/intel64/locore.S | 51 +------------------------- 3 files changed, 70 insertions(+), 114 deletions(-) create mode 100644 arch/x86/core/common.S diff --git a/arch/x86/core/common.S b/arch/x86/core/common.S new file mode 100644 index 00000000000..7152c053414 --- /dev/null +++ b/arch/x86/core/common.S @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* + * This is included by ia32/crt0.S and intel64/locore.S + * at their 32-bit entry points to cover common ground. + */ + +#ifdef CONFIG_MULTIBOOT_INFO + /* + * If we were loaded by a multiboot-compliant loader, then EAX + * contains MULTIBOOT_EAX_MAGIC and EBX points to a valid 'struct + * multiboot_info'; otherwise EBX is just junk. Check EAX early + * before it's clobbered and leave a sentinel (0) in EBX if invalid. + * The valid in EBX will be the argument to z_x86_prep_c(), so the + * subsequent code must, of course, be sure to preserve it meanwhile. + */ + + cmpl $MULTIBOOT_EAX_MAGIC, %eax + je 1f + xorl %ebx, %ebx +1: +#endif + +#ifdef CONFIG_BOOT_TIME_MEASUREMENT + /* + * Boot time measurements use TSC as a datum; zero it. + */ + + xorl %eax, %eax + xorl %edx, %edx + movl $X86_TIME_STAMP_COUNTER_MSR, %ecx + wrmsr +#endif + +#ifdef CONFIG_PIC_DISABLE + /* + * "Disable" legacy i8259 interrupt controllers. Note that we + * can't actually disable them, but we mask all their interrupt + * sources which is effectively the same thing (almost). + */ + + movb $0xff, %al + outb %al, $0x21 + outb %al, $0xA1 +#endif + +#ifdef CONFIG_MULTIBOOT + jmp 1f + + .align 4 + .long MULTIBOOT_HEADER_MAGIC + .long MULTIBOOT_HEADER_FLAGS + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) +#ifdef CONFIG_MULTIBOOT_FRAMEBUF + .fill 5,4,0 /* (unused exec layout) */ + .long 0 /* linear graphics mode */ + .long CONFIG_MULTIBOOT_FRAMEBUF_X /* width */ + .long CONFIG_MULTIBOOT_FRAMEBUF_Y /* height */ + .long 32 /* depth */ +#endif /* CONFIG_MULTIBOOT_FRAMEBUF */ +1: +#endif diff --git a/arch/x86/core/ia32/crt0.S b/arch/x86/core/ia32/crt0.S index 48d596de08c..a0cdfd25f26 100644 --- a/arch/x86/core/ia32/crt0.S +++ b/arch/x86/core/ia32/crt0.S @@ -43,37 +43,7 @@ SECTION_FUNC(TEXT_START, __start) -#ifdef CONFIG_MULTIBOOT_INFO - /* - * If we were loaded by a multiboot-compliant loader, then EAX - * contains MULTIBOOT_EAX_MAGIC and EBX points to a 'struct - * multiboot_info' somewhere in memory that the kernel load - * image doesn't claim. Since the kernel will consider such memory - * "free", we must copy the contents of the struct before the kernel - * decides to use that RAM for something else. However, we can't - * effect the copy until after the BSS is initialized. - * - * EBX isn't touched until the copy is made; even function calls will - * preserve it (it's callee-save in the SysV ABI). But EAX will be - * clobbered, so we check for the magic now and leave a sentinel in - * EBX (0) if the multiboot data isn't valid. - */ - - cmpl $MULTIBOOT_EAX_MAGIC, %eax - je 1f - xorl %ebx, %ebx -1: -#endif - -#ifdef CONFIG_BOOT_TIME_MEASUREMENT - /* - * Reset the TSC to 0, since that's the datum for boot metrics. - */ - xorl %eax, %eax - xorl %edx, %edx - movl $X86_TIME_STAMP_COUNTER_MSR, %ecx - wrmsr -#endif +#include "../common.S" /* Enable write-back caching by clearing the NW and CD bits */ movl %cr0, %eax @@ -265,17 +235,6 @@ __csSet: #endif lidt z_x86_idt /* load 32-bit operand size IDT */ -#if defined(CONFIG_PIC_DISABLE) - /* - * "Disable" legacy i8259 interrupt controllers. Note that we - * can't actually disable them, but we mask all their interrupt - * sources which is effectively the same thing (almost). - */ - movb $0xff, %al /* all bits set = mask all interrupts */ - outb %al, $0x21 /* set i8259 master mask (IRQs 0-7) */ - outb %al, $0xA1 /* set i8259 slave mask (IRQs 8-15) */ -#endif - pushl %ebx /* pointer to multiboot info, or NULL */ call z_x86_prep_c /* enter kernel; never returns */ @@ -390,29 +349,6 @@ z_x86_idt: .long _idt_base_address /* physical start address */ -#ifdef CONFIG_MULTIBOOT - /* - * The multiboot header must be in the first 8 Kb of the kernel image - * (not including the ELF section header(s)) and be aligned on a - * 4 byte boundary. See include/arch/x86/multiboot.h for more info. - */ - - .balign 4,0x90 - - .long MULTIBOOT_HEADER_MAGIC - .long MULTIBOOT_HEADER_FLAGS - .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) - -#ifdef CONFIG_MULTIBOOT_FRAMEBUF - .fill 5,4,0 /* (unused exec layout) */ - .long 0 /* linear graphics mode */ - .long CONFIG_MULTIBOOT_FRAMEBUF_X /* width */ - .long CONFIG_MULTIBOOT_FRAMEBUF_Y /* height */ - .long 32 /* depth */ -#endif /* CONFIG_MULTIBOOT_FRAMEBUF */ - -#endif /* CONFIG_MULTIBOOT */ - #ifdef CONFIG_SET_GDT /* GDT should be aligned on 8-byte boundary for best processor diff --git a/arch/x86/core/intel64/locore.S b/arch/x86/core/intel64/locore.S index 7440d7cc2df..64449fa4cf0 100644 --- a/arch/x86/core/intel64/locore.S +++ b/arch/x86/core/intel64/locore.S @@ -17,37 +17,9 @@ .globl __start __start: - /* - * multiboot starts us here in 32-bit flat mode with interrupts and - * paging disabled. first, check to see if EAX has a valid multiboot - * magic in it, and if not, zero EBX so we know it's bogus later. - * Remember not to clobber EBX until we've copied the boot info struct! - */ +#include "../common.S" -#ifdef CONFIG_MULTIBOOT_INFO - cmpl $MULTIBOOT_EAX_MAGIC, %eax - je 1f - xorl %ebx, %ebx -1: -#endif - - /* FIXME: ...resetting TSC here is common to IA32 and Intel64... */ - /* FIXME: ...disabling the PICs is common to IA32 and Intel64... */ - -#ifdef CONFIG_BOOT_TIME_MEASUREMENT - xorl %eax, %eax - xorl %edx, %edx - movl $X86_TIME_STAMP_COUNTER_MSR, %ecx - wrmsr -#endif - -#ifdef CONFIG_PIC_DISABLE - movb $0xff, %al - outb %al, $0x21 - outb %al, $0xA1 -#endif - - /* next, switch to our own GDT/IDT and stack. */ + /* switch to our own GDT/IDT and stack. */ lgdt gdt48 lidt idt48 @@ -141,25 +113,6 @@ x86_sse_init: mxcsr: .long X86_MXCSR_SANE -/* - * FIXME: The multiboot header is identical (for obvious reasons) to the - * version in ia32/crt0.S. They should be refactored into a common file. - */ - -#ifdef CONFIG_MULTIBOOT - .align 4 - .long MULTIBOOT_HEADER_MAGIC - .long MULTIBOOT_HEADER_FLAGS - .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) -#ifdef CONFIG_MULTIBOOT_FRAMEBUF - .fill 5,4,0 /* (unused exec layout) */ - .long 0 /* linear graphics mode */ - .long CONFIG_MULTIBOOT_FRAMEBUF_X /* width */ - .long CONFIG_MULTIBOOT_FRAMEBUF_Y /* height */ - .long 32 /* depth */ -#endif /* CONFIG_MULTIBOOT_FRAMEBUF */ -#endif - /* * void z_arch_switch(void *switch_to, void **switched_from); *