diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a8cf05d676a..0757e7d841d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -43,7 +43,240 @@ source "misc/Kconfig" source "arch/x86/core/Kconfig" -source "arch/x86/bsp/Kconfig" +menu "BSP General Configuration" + +choice +prompt "BSP Configuration" +default BSP_PCPENTIUM4 + +config BSP_ATOM_N28XX + bool "Minimum configuration for ATOM N28XX BSP" + select CPU_PENTIUM4 + select IOAPIC + select LOAPIC + select LOAPIC_TIMER + select EOI_HANDLER_SUPPORTED + select BOOTLOADER_UNKNOWN + select EXTRA_SERIAL_PORT + select SERIAL_INTERRUPT_LEVEL + select CUSTOM_RANDOM_GENERATOR + select BSP_GENERIC_PC + +config BSP_PCMINUTEIA + bool "Minimum configuration for MINUTE IA BSP" + select CPU_MINUTEIA + select PIC + select PIT + select BOI_HANDLER_SUPPORTED + select EOI_HANDLER_SUPPORTED + select BOOTLOADER_UNKNOWN + select EXTRA_SERIAL_PORT + select BSP_GENERIC_PC + +config BSP_PCPENTIUM4 + bool "Minimum configuration for PENTIUM 4 BSP" + select CPU_PENTIUM4 + select PIC + select PIT + select BOI_HANDLER_SUPPORTED + select EOI_HANDLER_SUPPORTED + select BOOTLOADER_UNKNOWN + select EXTRA_SERIAL_PORT + select BSP_GENERIC_PC + +config BSP_QUARK + bool "Minimum configuration for QUARK BSP" + select CPU_MINUTEIA + select IOAPIC + select HPET_TIMER + select EOI_HANDLER_SUPPORTED + select BOOTLOADER_UNKNOWN + select EXTRA_SERIAL_PORT + select LINK_AUX_COMPILER_LIBS + select NS16550 + select PCI + +endchoice + +config BSP_GENERIC_PC + bool + default n + select NS16550 + + +choice +prompt "Intel Processor" +default CPU_PENTIUM4 + +config CPU_MINUTEIA + bool "Minute IA" + help + This option signifies the use of a CPU from the Minute IA family. + +config CPU_PENTIUM4 + bool "Pentium 4" + help + This option signifies the use of a CPU from the Pentium 4 family. +endchoice + +config ADVANCED_IDLE + bool + prompt "Advanced idle state" + default n + depends on ADVANCED_POWER_MANAGEMENT && ADVANCED_IDLE_SUPPORTED + help + This option enables the kernel to interface to a custom advanced idle + power saving manager. This permits the system to enter a custom + power saving state when the kernel becomes idle for extended periods, + and then to restore the system to its previous state (rather than + booting up from scratch) when the kernel is re-activated. + +config ADV_IDLE_STACK_SIZE + int + prompt "Advanced idle state stack size" + default 16 + depends on ADVANCED_IDLE + help + This option defines the size of the separate stack used during the + system state check while the booting up. A separate stack is used + to avoid memory corruption on the system re-activation from power + down mode. The stack size must be large enough to hold the return + address (4 bytes) and the _AdvIdleCheckSleep() stack frame. + +config CPU_MIGHT_SUPPORT_CLFLUSH + bool + default n + help + If a BSP uses a processor that possibly implements CLFLUSH, change + the default in that BSP's config file. + +#FIXME This options is not being used in the current code base. +config CLFLUSH_INSTRUCTION_SUPPORTED + bool + prompt "CLFLUSH instruction supported" if CPU_MIGHT_SUPPORT_CLFLUSH + depends on CPU_MIGHT_SUPPORT_CLFLUSH + default n + help + Only enable this if the CLFLUSH instruction is supported, so that + an implementation of _SysCacheFlush() that uses CLFLUSH is made + available, instead of the one using WBINVD. + +menu "Specific CPU Capability Support" + +config ISA_IA32 + bool + default y if CPU_MINUTEIA || CPU_PENTIUM4 + default n + help + This option signifies the use of a CPU based on the Intel IA-32 + instruction set architecture. + +config HARDWARE_BP_SUPPORTED + def_bool y + depends on ISA_IA32 + help + This option signifies that the target supports hardware-based + instruction breakpoints and/or data watchpoints. + +config TICKLESS_IDLE_UNSUPPORTED + prompt "Tickless Idle Unsupported" + bool + default n + help + This option signifies the use of an Intel CPU that lacks + support for tickless idle. + +config CMOV_UNSUPPORTED + def_bool y + depends on CPU_MINUTEIA + help + This option signifies the use of an Intel CPU that lacks support + for the CMOV instruction. + +config CPU_FLOAT_UNSUPPORTED + def_bool y + depends on CPU_MINUTEIA + select CPU_SSE_UNSUPPORTED + help + This option signifies the use of an Intel CPU that lacks support + for floating point operations. + +config CPU_SSE_UNSUPPORTED + bool "CPU SSE unsupported" + default n + help + This option signifies the use of an Intel CPU that lacks support + for SSEx instructions (i.e. those which pre-date Pentium III). + +config CACHE_LINE_SIZE + int "Cache line size" + default 64 if CPU_PENTIUM4 + default 0 + help + Size in bytes of a CPU cache line. + +endmenu + +menu "Specific BSP Capability Support" +config DYNAMIC_INT_STUBS + bool "Dynamic INT stubs" + default n + help + This option allows a BSP's drivers to install interrupt handlers + at run time, if desired. If not enabled, interrupt handlers can only + be installed statically when the image is created. + +config PROT_MODE_SWITCH_PROMPT + bool "Prot Mode switch prompt" + default n + help + This option allows users to select the value of the PROT_MODE_SWITCH + configuration option. + +config ADVANCED_IDLE_SUPPORTED + bool "Advanced idle supported" + default n + help + This option signifies that the target supports the ADVANCED_IDLE + configuration option. + +endmenu + +config BOOTLOADER_UNKNOWN + bool + default n + help + This option signifies that the target has an unknown bootloader + or that it supports multiple ways of booting and it isn't clear + at build time which method is to be used. When this option is enabled + the BSP may have to do extra work to ensure a propert startup. + +menu "Boot Sequence Options" +depends on PROT_MODE_SWITCH_PROMPT + +config PROT_MODE_SWITCH + bool + prompt "Switch to 32-bit protected mode when booting" + default n + depends on PROT_MODE_SWITCH_PROMPT + help + This option causes the kernel to transition from real mode (16-bit) + to protected mode (32-bit) during its initial booting sequence. + +config BOOT_A20_ENABLE + bool "Boot A20 enable" + depends on PROT_MODE_SWITCH + default n + help + This option causes the A20 line to be enabled during the transition + from real mode (16-bit) to protected mode (32-bit) during its initial + booting sequence. + +endmenu + + +endmenu + menu "Floating Point Options" depends on !CPU_FLOAT_UNSUPPORTED diff --git a/arch/x86/Makefile b/arch/x86/Makefile index f5b30bb2fc6..c18ed7f62c9 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -1,6 +1,13 @@ -obj-y = core/ -obj-y += bsp/ +obj-y = crt0.o sys_fatal_error_handler.o driver_static_irq_stubs.o + +ifneq ($(CONFIG_CLFLUSH_INSTRUCTION_SUPPORTED),y) +obj-y += cache_s.o +endif + +obj-$(CONFIG_CLFLUSH_INSTRUCTION_SUPPORTED) += cache.o + +obj-y += core/ obj-$(CONFIG_MICROKERNEL) += task/ obj-$(CONFIG_BSP_QUARK) += quark/ obj-$(CONFIG_BSP_GENERIC_PC) += generic_pc/ diff --git a/arch/x86/bsp/Makefile b/arch/x86/bsp/Makefile deleted file mode 100644 index 4beec990581..00000000000 --- a/arch/x86/bsp/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -ccflags-y +=-I$(srctree)/arch/x86/$(strip $(CONFIG_BSP_DIR)) -asflags-y +=-I$(srctree)/arch/x86/$(strip $(CONFIG_BSP_DIR)) - -obj-y = crt0.o sysFatalErrorHandler.o driver_static_irq_stubs.o - -ifneq ($(CONFIG_CLFLUSH_INSTRUCTION_SUPPORTED),y) -obj-y += cache_s.o -endif - -obj-$(CONFIG_CLFLUSH_INSTRUCTION_SUPPORTED) += cache.o - diff --git a/arch/x86/bsp/cache.c b/arch/x86/cache.c similarity index 100% rename from arch/x86/bsp/cache.c rename to arch/x86/cache.c diff --git a/arch/x86/cache_s.s b/arch/x86/cache_s.s new file mode 100644 index 00000000000..0f010109f95 --- /dev/null +++ b/arch/x86/cache_s.s @@ -0,0 +1,64 @@ +/* cache_s.s - cache manipulation */ + +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* +DESCRIPTION +This module contains functions for manipulating caches. +*/ + +#ifndef CONFIG_CLFLUSH_INSTRUCTION_SUPPORTED + +#define _ASMLANGUAGE +#include + + /* externs (internal APIs) */ + GTEXT(_SysCacheFlush) + +/******************************************************************************* +* +* _SysCacheFlush - flush a page to main memory +* +* This implementation flushes the whole cache. +* +* C signature: +* +* void _SysCacheFlush (VIRT_ADDR virt, size_t size) +* +* Both parameters are ignored in this implementation. +* +* RETURNS: N/A +*/ + +SECTION_FUNC(TEXT, _SysCacheFlush) + wbinvd + ret + +#endif /* !CONFIG_CLFLUSH_INSTRUCTION_SUPPORTED */ diff --git a/arch/x86/crt0.s b/arch/x86/crt0.s new file mode 100644 index 00000000000..6b24de8e72d --- /dev/null +++ b/arch/x86/crt0.s @@ -0,0 +1,637 @@ +/* crt0.s - crt0 module for the IA-32 boards */ + +/* + * Copyright (c) 2010-2014 Wind River Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* +DESCRIPTION +This module contains the initial code executed by the Zephyr OS ELF image +after having been loaded into RAM. + +INTERNAL +The CONFIG_PROT_MODE_SWITCH configuration option is no longer used and *all* +booting scenarios (e.g. via GRUB or any other multiboot compliant bootloader) +now assume that the system is already in 32-bit protected mode and address line +A20 is enabled. However, the code associated with CONFIG_PROT_MODE_SWITCH has +been left in place should future booting scenarios arise which require its use. +*/ + +#define _ASMLANGUAGE + +#include + + /* exports (private APIs) */ + + GTEXT(__start) + + /* externs */ + GTEXT(_Cstart) + + GDATA(_idt_base_address) + GDATA(_interrupt_stack) + + +#if defined(CONFIG_SSE) + GDATA(_sse_mxcsr_default_value) +#endif /* CONFIG_SSE */ + +#if defined(CONFIG_BOOT_TIME_MEASUREMENT) + GDATA(__start_tsc) +#endif + +#ifdef CONFIG_ADVANCED_IDLE + GDATA(_AdvIdleCheckSleep) + GDATA(_AdvIdleStart) +#endif /* CONFIG_ADVANCED_IDLE */ + +#ifdef CONFIG_PROT_MODE_SWITCH + + /* cold start code in 16-bit real mode */ + + /* + * Switch 'gas' into 16-bit mode, i.e. use a default operand and + * address size of 16 bits since the processor is executing in + * 16-bit real mode. The prevents the assembler from inserting + * 0x66 or 0x67 instruction prefixes when using 16-bit data values + * or 16-bit pointers. + */ + + .code16 + + .section ".xreset", "ax" + .balign 16,0x90 + +__start: +#ifdef CONFIG_BOOT_TIME_MEASUREMENT + /* + * Record BootTime from start of Kernel. + * Store value temporarily in Register EDI & ESI and + * write to memory once memory access is allowed. + * That is, once the data segment register has been setup to access + * the .data/.rodata/.bss section of the linked image. + */ + rdtsc + mov %eax, %esi /* low value */ + mov %edx, %edi /* high value */ +#endif + /* + * Ensure interrupts are disabled. Interrupts are enabled when + * the first kernel thread context switch occurs. + */ + + cli + + +/* + * BSPs that need to enable the A20 line to boot properly wil enable this + * option. + */ +#ifdef CONFIG_BOOT_A20_ENABLE + + /* + * Set the stack pointer to just before the start of the .text + * section. This needs to be performed before any BIOS invocations. + * + * Note that attempting to set the stack pointer to beyond the end of + * the static ELF image (indicated via the _end symbol) may result + * in pointer wrap-around for images with large BSS sections + * (since the processor is still in "real" mode and thus the stack + * pointer is only a 16 bits). + */ + + movl $__start, %esp + + /* + * Before switching to 32-bit protected mode, Gate-A20 must be + * enabled (legacy PC hardware issue). + * + * The classical method of enabling address line A20 via the 8042 + * keyboard controller will not be performed. Instead, it will be + * assumed that the board has a relatively modern BIOS which supports + * the following int 15h function: + * + * - int 15h: ax=2400 -> disable A20 + * - int 15h: ax=2401 -> enable A20 + * If successful: CF clear, AH = 00h + * On error: CF set, AH = status + * Status: 01h keyboard controller is in secure mode + * 86h function not supported + * - int 15h: ax=2402 -> query status A20 + * status (0: disabled, 1: enabled) is returned in AL + * - int 15h: ax=2403 -> query A20 support (kbd or port 92) + * status (bit 0: kbd, bit 1: port 92) is returned in BX + * + * Return values: + * If successful: carry flag (CF) clear, AH = 00h + * On error: carry flag (CF) set, AH = status + * Status: 01h keyboard controller is in secure mode + * 86h function not supported + * + * If the int15h method fails, then the system control port A + * (I/O port 0x92) method will be used. + */ + + movw $0x2401, %ax /* ax=2401 -> enable A20 */ + int $0x15 + jnc A20Enabled /* CF = 1 -> try I/O port 0x92 method */ + + /* try enabling Gate-A20 via system control port A (I/O port 0x92) */ + + movb $0x02, %al + outb %al, $0x92 + + xorl %ecx, %ecx +A20EnableWait: + inb $0x92, %al + andb $0x02, %al + loopz A20EnableWait + +A20Enabled: +#endif /* CONFIG_BOOT_A20_ENABLE */ + + /* load Interrupt Descriptor and Global Descriptor tables (IDT & GDT) */ + + lgdt %cs:_GdtRom /* load 32-bit operand size GDT */ + + movl %cr0, %eax /* move CR0 to EAX */ + orl $0x1, %eax /* set the Protection Enable (PE) bit */ + andl $0x9fffffff, %eax /* Enable write-back caching */ + movl %eax, %cr0 /* move EAX to CR0 */ + jmp %cs:vstartProtMode /* flush prefetch input queue */ + +vstartProtMode: + + /* + * At this point, the processor is executing in 32-bit protected + * mode, but the CS selector hasn't been loaded yet, i.e. the + * processor is still effectively executing instructions from a + * 16-bit code segment (thus the .code16 assembler directive still + * needs to be in effect. + */ + + movw $0x10,%ax /* data segment selector (entry = 3) */ + movw %ax,%ds /* set DS */ + movw %ax,%es /* set ES */ + movw %ax,%fs /* set FS */ + movw %ax,%gs /* set GS */ + movw %ax,%ss /* set SS */ + + /* this is 'ljmp $0x08:$vstart32BitCode': diab 5.9.1.0 does not encode + * it correctly */ + .byte 0xea + .long vstart32BitCode + .byte 0x08 + .byte 0x00 + + /* + * Switch 'gas' back to 32-bit data and address defaults. This + * can only be performed after loading the CS segment register + * (via an lcall instruction, for example) with a segment selector + * that describes a 32-bit code segment. + */ + .code32 + +SECTION_FUNC(TEXT_START, vstart32BitCode) + +#else /* !CONFIG_PROT_MODE_SWITCH */ + + /* processor is executing in 32-bit protected mode */ + + .balign 16,0x90 + +SECTION_FUNC(TEXT_START, __start) + +#ifdef CONFIG_BOOT_TIME_MEASUREMENT + /* + * Record BootTime from start of Kernel. + * Store value temporarily in Register edi & esi and + * write to memory once memory access is allowed. + * That is, once the data segment register has been setup to access + * the .data/.rodata/.bss section of the linked image. + */ + rdtsc + mov %eax, %esi /* low value */ + mov %edx, %edi /* high value */ +#endif + + /* Enable write-back caching by clearing the NW and CD bits */ + movl %cr0, %eax + andl $0x9fffffff, %eax + movl %eax, %cr0 + + /* + * Ensure interrupts are disabled. Interrupts are enabled when + * the first kernel thread context switch occurs. + */ + + cli + + /* + * Although the bootloader sets up an Interrupt Descriptor Table (IDT) + * and a Global Descriptor Table (GDT), the specification encourages + * booted operating systems to setup their own IDT and GDT. + */ + + lgdt _GdtRom /* load 32-bit operand size GDT */ + +#endif /* !CONFIG_PROT_MODE_SWITCH */ + + + lidt _Idt /* load 32-bit operand size IDT */ + + +#ifndef CONFIG_PROT_MODE_SWITCH + +#ifdef CONFIG_BOOTLOADER_UNKNOWN + /* + * Where we do not do the protected mode switch and the + * bootloader is unknown, do not make the assumption that the segment + * registers are set correctly. + * + * This is a special case for the generic_pc BSP, which must work for + * multiple platforms (QEMU, generic PC board, etc.). With other + * BSPs the bootloader is well known so assumptions can be made. + */ + movw $0x10, %ax /* data segment selector (entry = 3) */ + movw %ax, %ds /* set DS */ + movw %ax, %es /* set ES */ + movw %ax, %fs /* set FS */ + movw %ax, %gs /* set GS */ + movw %ax, %ss /* set SS */ + + /* this is 'ljmp $0x08:$_csSet': diab 5.9.1.0 does not encode + * it correctly */ + .byte 0xea + .long __csSet + .byte 0x08 + .byte 0x00 + +__csSet: +#endif /* CONFIG_BOOTLOADER_UNKNOWN */ + +#endif /* CONFIG_PROT_MODE_SWITCH */ + +#ifdef CONFIG_BOOT_TIME_MEASUREMENT + /* + * Store rdtsc result from temporary regiter ESI & EDI into memory. + */ + mov %esi, __start_tsc /* low value */ + mov %edi, __start_tsc+4 /* high value */ +#endif + +#ifdef CONFIG_ADVANCED_IDLE + + /* + * Set up the temporary stack to call the _AdvIdleCheckSleep routine + * We use the separate stack here in order to avoid the memory + * corruption if the system recovers from deep sleep + */ + movl $_AdvIdleStack, %esp + addl $CONFIG_ADV_IDLE_STACK_SIZE, %esp + + /* align to stack boundary: ROUND_DOWN (%esp, 4) */ + + andl $0xfffffffc, %esp + + /* + * Invoke _AdvIdleCheckSleep() routine that checks if we are restoring + * from deep sleep or not. The routine returns non-zero if the kernel + * is recovering from deep sleep and to 0 if a cold boot is needed. The + * kernel can skip floating point initialization, BSS initialization, + * and data initialization if recovering from deep sleep. + */ + + call _AdvIdleCheckSleep + cmpl $0, %eax + jne memInitDone + +#endif /* CONFIG_ADVANCED_IDLE */ + +#if !defined(CONFIG_FLOAT) + /* + * Force an #NM exception for floating point instructions + * since FP support hasn't been configured + */ + + movl %cr0, %eax /* move CR0 to EAX */ + orl $0x2e, %eax /* CR0[NE+TS+EM+MP]=1 */ + movl %eax, %cr0 /* move EAX to CR0 */ +#else + /* + * Permit use of x87 FPU instructions + * + * Note that all floating point exceptions are masked by default, + * and that _no_ handler for x87 FPU exceptions (#MF) is provided. + */ + + movl %cr0, %eax /* move CR0 to EAX */ + orl $0x22, %eax /* CR0[NE+MP]=1 */ + andl $~0xc, %eax /* CR0[TS+EM]=0 */ + movl %eax, %cr0 /* move EAX to CR0 */ + + fninit /* set x87 FPU to its default state */ + + #if defined(CONFIG_SSE) + /* + * Permit use of SSE instructions + * + * Note that all SSE exceptions are masked by default, + * and that _no_ handler for SSE exceptions (#XM) is provided. + */ + + movl %cr4, %eax /* move CR4 to EAX */ + orl $0x200, %eax /* CR4[OSFXSR] = 1 */ + andl $~0x400, %eax /* CR4[OSXMMEXCPT] = 0 */ + movl %eax, %cr4 /* move EAX to CR4 */ + + ldmxcsr _sse_mxcsr_default_value /* initialize SSE control/status reg */ + + #endif /* CONFIG_SSE */ + +#endif /* !CONFIG_FLOAT */ + +#ifdef CONFIG_XIP + /* + * copy DATA section from ROM to RAM region + * DATA is followed by BSS section. + * Given that BSS section is initialized after this copy, we can + * safely over-write into the next section. + * Note: __data_num_words is a multiple of 4 bytes + * rounded up to next 4 bytes. + * Note: the sections might not be 4 byte aligned. + */ + + movl $__data_ram_start, %edi /* DATA in RAM (dest) */ + movl $__data_rom_start, %esi /* DATA in ROM (src) */ + movl $__data_num_words, %ecx /* Size of DATA in quad bytes */ + je copyDataDone + + #ifdef CONFIG_SSE + /* copy 16 bytes at a time using XMM until < 16 bytes remain */ + + movl %ecx ,%edx /* save number of quad bytes */ + shrl $2, %ecx /* How many 16 bytes? */ + je dataWords + +dataDQ: + movdqu (%esi), %xmm0 + movdqu %xmm0, (%edi) + addl $16, %esi + addl $16, %edi + loop dataDQ + +dataWords: + movl %edx, %ecx /* restore # quad bytes */ + andl $0x3, %ecx /* only need to copy at most 3 quad bytes */ + #endif /* CONFIG_SSE */ + + rep + movsl /* copy data 4 bytes at a time */ +copyDataDone: + +#endif /* CONFIG_XIP */ + + /* + * Clear BSS: bzero (__bss_start, __bss_num_words*4) + * + * It's assumed that BSS size will be a multiple of a long (4 bytes), + * and aligned on a double word (32-bit) boundary + */ + +#ifdef CONFIG_SSE + + /* use XMM register to clear 16 bytes at a time */ + + pxor %xmm0, %xmm0 /* zero out xmm0 register */ + movl $__bss_start, %edi /* load BSS start address */ + movl $__bss_num_words, %ecx /* number of quad bytes in .bss */ + movl %ecx, %edx /* make a copy of # quad bytes */ + shrl $2, %ecx /* How many multiples of 16 byte ? */ + je bssWords +bssDQ: + movdqu %xmm0, (%edi) /* zero 16 bytes... */ + addl $16, %edi + loop bssDQ + + /* fall through to handle the remaining double words (32-bit chunks) */ + +bssWords: + xorl %eax, %eax /* fill memory with 0 */ + movl %edx, %ecx /* move # quad bytes into ECX (for rep) */ + andl $0x3, %ecx /* only need to zero at most 3 quad bytes */ + cld + rep + stosl /* zero memory per 4 bytes */ + +#else /* !CONFIG_SSE */ + + /* clear out BSS double words (32-bits at a time) */ + + xorl %eax, %eax /* fill memory with 0 */ + movl $__bss_start, %edi /* load BSS start address */ + movl $__bss_num_words, %ecx /* number of quad bytes */ + cld + rep + stosl /* zero memory per 4 bytes */ + +#endif /* CONFIG_SSE */ + +memInitDone: + + /* + * Set the stack pointer to the area used for the interrupt stack. + * Note this stack is only used during the execution of __start() and + * _Cstart(), i.e. only until the multi-tasking kernel is + * initialized. The dual-purposing of this area of memory is safe since + * interrupts are disabled until the first context switch. + */ + + movl $_interrupt_stack, %esp + addl $CONFIG_ISR_STACK_SIZE, %esp + + /* align to stack boundary: ROUND_DOWN (%esp, 4) */ + + andl $0xfffffffc, %esp + + /* activate RAM-based Global Descriptor Table (GDT) */ + + lgdt %ds:_gdt + + + +#if defined (CONFIG_ADVANCED_IDLE) + /* + * Invoke _AdvIdleStart(_Cstart, _gdt, _GlobalTss) by jumping to it. + * If it's a cold boot, this routine jumps to _Cstart and the normal + * kernel boot sequence continues; otherwise, it uses the TSS info + * saved in the GDT to resumes kernel processing at the point it was + * when the system went into deep sleep; that is, _AdvIdleFunc() + * completes and returns a non-zero value. + */ + + pushl $_GlobalTss + pushl $_gdt + pushl $_Cstart + call _AdvIdleStart +#else + /* Jump to C portion of kernel initialization and never return */ + + jmp _Cstart + +#endif /* CONFIG_ADVANCED_IDLE */ + +#if defined(CONFIG_SSE) + + /* SSE control & status register initial value */ + +_sse_mxcsr_default_value: + .long 0x1f80 /* all SSE exceptions clear & masked */ + +#endif /* CONFIG_SSE */ + + /* Interrupt Descriptor Table (IDT) definition */ + +_Idt: + .word (CONFIG_IDT_NUM_VECTORS * 8) - 1 /* limit: size of IDT-1 */ + + /* + * Physical start address = 0. When executing natively, this + * will be placed at the same location as the interrupt vector table + * setup by the BIOS (or GRUB?). + */ + + .long _idt_base_address /* physical start address */ + + +#ifdef CONFIG_BOOTLOADER_UNKNOWN + /* Multiboot header definition is needed for some bootloaders */ + + /* + * 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. + */ + + .balign 4,0x90 + + .long 0x1BADB002 /* multiboot magic number */ + + /* + * Flags = no bits are being set, specifically bit 16 is not being + * set since the supplied kernel image is an ELF file, and the + * multiboot loader shall use the information from the program and + * section header to load and boot the kernel image. + */ + + .long 0x00000000 + + /* + * checksum = 32-bit unsigned value which, when added to the other + * magic fields (i.e. "magic" and "flags"), must have a 32-bit + * unsigned sum of zero. + */ + + .long -(0x1BADB002 + 0) +#endif /* CONFIG_BOOTLOADER_UNKNOWN */ + + +#ifdef CONFIG_PROT_MODE_SWITCH + /* Global Descriptor Table (GDT) definition */ + .section ".xreset", "ax" + .align 8 +#endif /* CONFIG_PROT_MODE_SWITCH */ + +_GdtRom: + .word _GdtRomEnd - _GdtRomEntries - 1 /* Limit on GDT */ + .long _GdtRomEntries /* table address: _GdtRomEntries */ + + + .balign 16,0x90 + + /* + * The following 3 GDT entries implement the so-called "basic + * flat model", i.e. a single code segment descriptor and a single + * data segment descriptor, giving the kernel access to a continuous, + * unsegmented address space. Both segment descriptors map the entire + * linear address space (i.e. 0 to 4 GB-1), thus the segmentation + * mechanism will never generate "out of limit memory reference" + * exceptions even if physical memory does not reside at the referenced + * address. + * + * The 'A' (accessed) bit in the type field is _not_ set for all the + * data/code segment descriptors to accomodate placing these entries + * in ROM, since such use is not planned for this platform. + */ + +_GdtRomEntries: + + /* Entry 0 (selector=0x0000): The "NULL descriptor" */ + + .word 0x0000 + .word 0x0000 + .byte 0x00 + .byte 0x00 + .byte 0x00 + .byte 0x00 + + /* Entry 1 (selector=0x0008): Code descriptor: DPL0 */ + + .word 0xffff /* limit: xffff */ + .word 0x0000 /* base : xxxx0000 */ + .byte 0x00 /* base : xx00xxxx */ + .byte 0x9a /* Code e/r, Present, DPL0 */ + .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ + .byte 0x00 /* base : 00xxxxxx */ + + /* Entry 2 (selector=0x0010): Data descriptor: DPL0 */ + + .word 0xffff /* limit: xffff */ + .word 0x0000 /* base : xxxx0000 */ + .byte 0x00 /* base : xx00xxxx */ + .byte 0x92 /* Data r/w, Present, DPL0 */ + .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ + .byte 0x00 /* base : 00xxxxxx */ + + +#ifdef CONFIG_PROT_MODE_SWITCH + /* Reset vector */ + .code16 + .section ".xresetv", "ax" +_ResetVector: + jmp __start +#endif /* CONFIG_PROT_MODE_SWITCH */ + +_GdtRomEnd: + +#ifdef CONFIG_ADVANCED_IDLE + .section .NOINIT + .balign 4,0x90 +_AdvIdleStack: + .fill CONFIG_ADV_IDLE_STACK_SIZE +#endif diff --git a/arch/x86/driver_static_irq_stubs.s b/arch/x86/driver_static_irq_stubs.s new file mode 100644 index 00000000000..69fde727cfd --- /dev/null +++ b/arch/x86/driver_static_irq_stubs.s @@ -0,0 +1,195 @@ +/* driver_static_irq_stubs.s - interrupt stubs */ + +/* + * Copyright (c) 2012-2015, Wind River Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3) Neither the name of Wind River Systems nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +DESCRIPTION +This module contains the static interrupt stubs for the various drivers employed +by x86 BSPs. +*/ + +#define _ASMLANGUAGE + +#ifndef CONFIG_DYNAMIC_INT_STUBS + +#include +#include +#include +#include +#include + + /* exports (internal APIs) */ +#if defined(CONFIG_LOAPIC_TIMER) + GTEXT(_loapic_timer_irq_stub) +#endif + +#if defined(CONFIG_HPET_TIMER) + GTEXT(_hpetIntStub) +#endif + +#if defined (CONFIG_PIC) + GTEXT(_masterStrayIntStub) + GTEXT(_slaveStrayIntStub) +#endif + +#if defined (CONFIG_PIT) + GTEXT(_i8253_interrupt_stub) +#endif + +#if defined(CONFIG_BLUETOOTH_UART) + GTEXT(_bluetooth_uart_stub) +#endif /* CONFIG_BLUETOOTH */ + +#if defined(CONFIG_CONSOLE_HANDLER) + GTEXT(_console_uart_stub) +#endif /* CONFIG_CONSOLE_HANDLER */ + + /* externs (internal APIs) */ + + GTEXT(_IntEnt) + GTEXT(_IntExit) + +#if defined(CONFIG_LOAPIC_TIMER) +SECTION_FUNC (TEXT, _loapic_timer_irq_stub) + call _IntEnt /* Inform kernel interrupt has begun */ + pushl $0 /* Push dummy parameter */ + call _timer_int_handler /* Call actual interrupt handler */ + call _loapic_eoi /* Inform loapic interrupt is done */ + addl $4, %esp /* Clean-up stack from push above */ + jmp _IntExit /* Inform kernel interrupt is done */ +#endif /* CONFIG_LOAPIC_TIMER */ + +#if defined(CONFIG_HPET_TIMER) +SECTION_FUNC(TEXT, _hpetIntStub) + call _IntEnt /* Inform kernel interrupt has begun */ + pushl $0 /* Push dummy parameter */ + call _timer_int_handler /* Call actual interrupt handler */ + call _ioapic_eoi /* Inform ioapic interrupt is done */ + addl $4, %esp /* Clean-up stack from push above */ + jmp _IntExit /* Inform kernel interrupt is done */ +#endif /* CONFIG_HPET_TIMER */ + +#if defined(CONFIG_PIC) +SECTION_FUNC(TEXT, _masterStrayIntStub) + /* + * Handle possible spurious (stray) interrupts on IRQ 7. Since on this + * particular BSP, no device is hooked up to IRQ 7, a C level ISR is + * not called as the call to the BOI routine will not return. + */ + call _IntEnt /* Inform kernel interrupt has begun */ + call _i8259_boi_master /* Call the BOI routine (won't return) */ + + /* + * If an actual device was installed on IRQ 7, then the BOI may return, + * indicating a real interrupt was asserted on IRQ 7. + * The following code should be invoked in this case to invoke the ISR: + * + * pushl $param /+ Push argument to ISR +/ + * call ISR /+ Call 'C' level ISR +/ + * addl $4, %esp /+ pop arg to ISR +/ + * jmp _IntExit /+ Inform kernel interrupt is done +/ + */ + +SECTION_FUNC(TEXT, _slaveStrayIntStub) + /* + * Handle possible spurious (stray) interrupts on IRQ 15 (slave PIC + * IRQ 7). Since on this particular BSP, no device is hooked up to + * IRQ 15, a C level ISR is not called as the call the BOI routine + * will not return. + */ + call _IntEnt /* Inform kernel interrupt has begun */ + call _i8259_boi_slave /* Call the BOI routine (won't return) */ + + /* + * If an actual device was installed on IRQ 15, then the BOI may return, + * indicating a real interrupt was asserted on IRQ 15. + * The following code should be invoked in this case to invoke the ISR: + * + * pushl $param /+ Push argument to ISR +/ + * call ISR /+ Call 'C' level ISR +/ + * addl $4, %esp /+ pop arg to ISR +/ + * jmp _IntExit /+ Inform kernel interrupt is done +/ + */ +#endif /* CONFIG_PIC */ + +#if defined(CONFIG_PIT) +SECTION_FUNC(TEXT, _i8253_interrupt_stub) + call _IntEnt /* Inform kernel interrupt has begun */ + pushl $0 /* Push dummy parameter */ + call _timer_int_handler /* Call actual interrupt handler */ + call _i8259_eoi_master /* Inform the PIC interrupt is done */ + addl $4, %esp /* Clean-up stack from push above */ + jmp _IntExit /* Inform kernel interrupt is done */ +#endif /* CONFIG_PIT */ + +#if defined(CONFIG_BLUETOOTH_UART) +#if defined(CONFIG_PIC) +SECTION_FUNC(TEXT, _bluetooth_uart_stub) + call _IntEnt /* Inform kernel interrupt has begun */ + pushl $0 /* Push dummy parameter */ + call bt_uart_isr /* Call actual interrupt handler */ + call _i8259_eoi_master /* Inform the PIC interrupt is done */ + addl $4, %esp /* Clean-up stack from push above */ + jmp _IntExit /* Inform kernel interrupt is done */ +#elif defined(CONFIG_IOAPIC) +SECTION_FUNC(TEXT, _bluetooth_uart_stub) + call _IntEnt /* Inform kernel interrupt has begun */ + pushl $0 /* Push dummy parameter */ + call bt_uart_isr /* Call actual interrupt handler */ + call _ioapic_eoi /* Inform the PIC interrupt is done */ + addl $4, %esp /* Clean-up stack from push above */ + jmp _IntExit /* Inform kernel interrupt is done */ +#endif /* CONFIG_PIC */ +#endif /* CONFIG_BLUETOOTH_UART */ + +#if defined(CONFIG_CONSOLE_HANDLER) + +#if defined(CONFIG_PIC) +SECTION_FUNC(TEXT, _console_uart_stub) + call _IntEnt /* Inform kernel interrupt has begun */ + pushl $0 /* Push dummy parameter */ + call uart_console_isr /* Call actual interrupt handler */ + call _i8259_eoi_master /* Inform the PIC interrupt is done */ + addl $4, %esp /* Clean-up stack from push above */ + jmp _IntExit /* Inform kernel interrupt is done */ +#elif defined(CONFIG_IOAPIC) +SECTION_FUNC(TEXT, _console_uart_stub) + call _IntEnt /* Inform kernel interrupt has begun */ + pushl $0 /* Push dummy parameter */ + call uart_console_isr /* Call actual interrupt handler */ + call _ioapic_eoi /* Inform the PIC interrupt is done */ + addl $4, %esp /* Clean-up stack from push above */ + jmp _IntExit /* Inform kernel interrupt is done */ +#endif /* CONFIG_PIC */ + +#endif /* CONFIG_CONSOLE_HANDLER */ + +#endif /* !CONFIG_DYNAMIC_INT_STUBS */ diff --git a/arch/x86/bsp/sysFatalErrorHandler.c b/arch/x86/sys_fatal_error_handler.c similarity index 100% rename from arch/x86/bsp/sysFatalErrorHandler.c rename to arch/x86/sys_fatal_error_handler.c