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 <charles.youse@intel.com>
This commit is contained in:
parent
25a7cc1136
commit
418e5c1b38
3 changed files with 70 additions and 114 deletions
67
arch/x86/core/common.S
Normal file
67
arch/x86/core/common.S
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Intel Corporation
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <arch/x86/multiboot.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
|
@ -43,37 +43,7 @@
|
||||||
|
|
||||||
SECTION_FUNC(TEXT_START, __start)
|
SECTION_FUNC(TEXT_START, __start)
|
||||||
|
|
||||||
#ifdef CONFIG_MULTIBOOT_INFO
|
#include "../common.S"
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
/* Enable write-back caching by clearing the NW and CD bits */
|
/* Enable write-back caching by clearing the NW and CD bits */
|
||||||
movl %cr0, %eax
|
movl %cr0, %eax
|
||||||
|
@ -265,17 +235,6 @@ __csSet:
|
||||||
#endif
|
#endif
|
||||||
lidt z_x86_idt /* load 32-bit operand size IDT */
|
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 */
|
pushl %ebx /* pointer to multiboot info, or NULL */
|
||||||
call z_x86_prep_c /* enter kernel; never returns */
|
call z_x86_prep_c /* enter kernel; never returns */
|
||||||
|
|
||||||
|
@ -390,29 +349,6 @@ z_x86_idt:
|
||||||
.long _idt_base_address /* physical start address */
|
.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
|
#ifdef CONFIG_SET_GDT
|
||||||
|
|
||||||
/* GDT should be aligned on 8-byte boundary for best processor
|
/* GDT should be aligned on 8-byte boundary for best processor
|
||||||
|
|
|
@ -17,37 +17,9 @@
|
||||||
.globl __start
|
.globl __start
|
||||||
__start:
|
__start:
|
||||||
|
|
||||||
/*
|
#include "../common.S"
|
||||||
* 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!
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef CONFIG_MULTIBOOT_INFO
|
/* switch to our own GDT/IDT and stack. */
|
||||||
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. */
|
|
||||||
|
|
||||||
lgdt gdt48
|
lgdt gdt48
|
||||||
lidt idt48
|
lidt idt48
|
||||||
|
@ -141,25 +113,6 @@ x86_sse_init:
|
||||||
|
|
||||||
mxcsr: .long X86_MXCSR_SANE
|
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);
|
* void z_arch_switch(void *switch_to, void **switched_from);
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue